Function.RegisterNamespace("System.Web");

System.Web.Request=function(){
    var _resource;
    var _transport;
    var _user;
    var _password;
    
    function Request(resource,user,password){
        _resource=resource;
        _transport=getTransport();
        _user=user;
        _password=password;
    }
    Request.apply(this,arguments);

    // IDisposable Members
    this.Dispose=function(){
        this.Abort();
        _transport=null;
    };

    // Public Methods
    this.Abort=function(){
        if(_transport)_transport.abort();
    };
    
    this.Begin=function(parameters,callback,verb,headers,binary){
        if(!_transport)throw new Error("System.Web.Request.Begin: Request has already been disposed.");
        if(callback!=undefined&&!Object.IsType(Function,callback))throw new Error("System.Web.Request.Begin: 'callback' must be a valid Function pointer.");
        _transport.abort();
        _transport.onreadystatechange = Function.GetDelegate(Transport_ReadyStateChange, _transport, callback);
        getResponse(parameters,verb,headers,true,callback,!!binary);
    };

    this.Get=function(parameters,verb,headers,binary){
        if(!_transport)throw new Error("System.Web.Request.Begin: Request has already been disposed.");
        _transport.onreadystatechange=Transport_ReadyStateChange;
        return getResponse(parameters,verb,headers,false,null,!!binary);
    };

    // Private methods
    function getParamList(parameters){
        var paramList=[];
        if(parameters){
            for(var x in parameters){
                paramList.push(String.Format("{0}={1}",x,encodeURIComponent(parameters[x])));
            }
        }
        return paramList.join('&');
    }
    
    function getResponse(parameters,verb,headers,async,callback,binary){
        try{
            if(!verb)verb="GET";
            var paramList=!binary&&getParamList(parameters);
            var url=_resource;
            switch(verb.toUpperCase()){
                case "HEAD":
                case "GET":
                    if(paramList)url=String.Format("{0}{2}{1}",url,paramList,!~url.indexOf('?')?'?':'&');
                    break;
            }
            _transport.open(verb,url,!!async,_user||null,_password||null);
            if(paramList){
                if(binary){
                    _transport.overrideMimeType("text/plain; charset=x-user-defined-binary");  
                    transport.sendAsBinary(parameters.getAsBinary());
                }else{
                    _transport.send(paramList);
                }
            }else _transport.send();
            if(!async)return getTransportResult();
        }catch(e){
            var error=String.Format("System.Web.Request.getResponse: An error occurred while retrieving the resource: {0}",e);
            if(!async)throw new Error(error);
            if(callback)callback(null,error);
        }
    }
    
    function getResponseHeaders(){
        var responseHeaders={};
        var headers=_transport.getAllResponseHeaders().split("\r\n");
        for(var i=0;i<headers.length;i++){
            if(!headers[i])continue;
            var header=headers[i].split(':');
            responseHeaders[String.Trim(header[0])]=String.Trim(header[1]);
        }
        return responseHeaders;
    }
    
    function getTransport(){
        if(typeof(XMLHttpRequest)!='undefined')return new XMLHttpRequest();
        if(typeof(ActiveXObject)!='undefined')return new ActiveXObject('Microsoft.XMLHTTP');
        return null;
    }
    
    function getTransportResult(){
        var result=new String(_transport.responseText);
        result.Headers=getResponseHeaders();
        result.Status=_transport.status;
        return result;
    }
    
    // Events
    function Transport_ReadyStateChange(callback){
        if(_transport.readyState!=4)return;
        var result=getTransportResult();
        var success=_transport.status==200;
        if(callback)callback(success&&result||null,!success&&result||null);
    }
};